#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import math
from PySide6.QtWidgets import *
from PySide6.QtCore import Qt, QSize, QEvent
from PySide6.QtGui import QAction, QIcon, QColor
import pandas as pd
from decimal import Decimal, getcontext, ROUND_HALF_UP

from Compute import EstimateEigenvalues, OtherParameters, TrueThickness, AngularDifference, PointAPrediction, \
    TrueInclination
from WellTrajectoryData import WellTrajectoryData
from FindData import ExcelFinder
# 设置全局舍入规则为四舍五入
getcontext().rounding = ROUND_HALF_UP

# 定义不同列的显示精度
DISPLAY_FORMATS = {
    # 主表格显示精度
    'main_table': {
        0: '.2f',  # 井深(m)
        1: '.2f',  # 井斜(°)
        2: '.2f',  # 方位(°)
        3: '.4f',  # 垂深(m)
        4: '.4f',  # 南北坐标(m)
        5: '.4f',  # 东西坐标(m)
        6: '.4f',  # 闭合方位(°)
        7: '.4f',  # 闭合位移(m)
        8: '.4f',  # 视平位移(m)
        9: '.4f',  # 狗腿度(°/30m)
        10: '.4f',  # 纵坐标(X)
        11: '.4f'  # 横坐标(Y)
    },
    # 真厚度表格显示精度
    'thickness_table': {
        0: '.2f',  # 深度(m)
        1: '.2f',  # 地层真倾向(°)
        2: '.2f',  # 地层真倾角(°)
        3: '.2f',  # 井轨迹方位(°)
        4: '.4f'  # 沿井轨迹视倾角(°)
    }
}

# 计算精度（使用更高的精度进行计算）
CALCULATION_PRECISION = Decimal('0.0000000000')  # 10位小数精度


class CollapsibleDockWidget(QDockWidget):
    """可折叠的停靠窗口"""

    def __init__(self, title, parent=None):
        super().__init__(title, parent)
        self.setFeatures(QDockWidget.DockWidgetClosable |
                         QDockWidget.DockWidgetMovable |
                         QDockWidget.DockWidgetFloatable)
        self.toggle_action = self.toggleViewAction()
        self.toggle_action.setText(f"切换{title}")


class WellTrajectorySystem(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.setup_dock_widgets()
        self.setup_central_widget()
        # self.setup_connections()

    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("最小曲率半径法计算井眼轨迹计算机程序")
        self.setGeometry(100, 100, 1280, 720)
        self.setup_toolbar()
        self.statusBar().showMessage("就绪")

    def setup_toolbar(self):
        """设置工具栏"""
        toolbar = self.addToolBar("主工具栏")
        toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        # 工具栏动作
        actions = [
            ("导入数据", "document-open", self.import_data),
            ("清空", "edit-clear", self.clear_data),
            ("导出", "document-save", self.export_data)
        ]

        # 添加视图切换动作
        view_toolbar = self.addToolBar("视图工具栏")
        view_toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        view_actions = [
            ("井眼轨迹", "view-1", lambda: self.switch_view(0)),
            ("夹角计算", "view-2", lambda: self.switch_view(1)),
            ("真厚度计算", "view-3", lambda: self.switch_view(2))
        ]

        for text, icon_name, handler in actions:
            action = QAction(QIcon.fromTheme(icon_name), text, self)
            action.triggered.connect(handler)
            toolbar.addAction(action)

        for text, icon_name, handler in view_actions:
            action = QAction(QIcon.fromTheme(icon_name), text, self)
            action.triggered.connect(handler)
            view_toolbar.addAction(action)

    def setup_dock_widgets(self):
        """设置停靠窗口"""
        # 左侧信息面板
        self.info_dock = CollapsibleDockWidget("井眼信息", self)
        info_widget = QWidget()
        info_layout = QVBoxLayout(info_widget)

        # 井号信息
        well_info = QGroupBox("井号信息")
        well_layout = QFormLayout(well_info)
        self.well_number = QLineEdit()
        well_layout.addRow("井号:", self.well_number)

        # 单位信息
        unit_info = QGroupBox("单位信息")
        unit_layout = QFormLayout(unit_info)
        self.unit_name = QLineEdit()
        unit_layout.addRow("单位:", self.unit_name)

        # 设计信息
        design_info = QGroupBox("设计信息")
        design_layout = QFormLayout(design_info)
        self.design_azimuth = QLineEdit("188.00")
        self.magnetic_declination = QLineEdit("0.00")
        design_layout.addRow("设计方位:", self.design_azimuth)
        design_layout.addRow("地磁偏角:", self.magnetic_declination)

        info_layout.addWidget(well_info)
        info_layout.addWidget(unit_info)
        info_layout.addWidget(design_info)
        info_layout.addStretch()

        self.info_dock.setWidget(info_widget)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.info_dock)

        # # 右侧参数面板
        # self.param_dock = CollapsibleDockWidget("计算参数", self)
        # param_widget = QWidget()
        # param_layout = QVBoxLayout(param_widget)

        # 添加参数控件
        param_group = QGroupBox("参数设置")
        param_form = QFormLayout(param_group)
        self.param1 = QLineEdit()
        self.param2 = QLineEdit()
        param_form.addRow("特征1:", self.param1)
        param_form.addRow("特征2:", self.param2)

        # param_layout.addWidget(param_group)
        # param_layout.addStretch()

        # self.param_dock.setWidget(param_widget)
        # self.addDockWidget(Qt.RightDockWidgetArea, self.param_dock)

    def setup_central_widget(self):
        """设置中央部件"""
        # 创建堆叠部件用于切换不同视图
        self.stack_widget = QStackedWidget()
        self.setCentralWidget(self.stack_widget)

        # 创建三个主要视图
        self.trajectory_view = self.create_trajectory_view()
        self.angle_view = self.create_angle_view()
        self.thickness_view = self.create_thickness_view()

        # 添加到堆叠部件
        self.stack_widget.addWidget(self.trajectory_view)
        self.stack_widget.addWidget(self.angle_view)
        self.stack_widget.addWidget(self.thickness_view)

    def create_trajectory_view(self):
        """创建井眼轨迹视图"""
        view = QWidget()
        layout = QVBoxLayout(view)

        # 创建特征值面板
        feature_group = QGroupBox("特征值输入")
        feature_layout = QGridLayout(feature_group)

        # 创建表头
        headers = ["井深(m)", "井斜(°)", "方位(°)", "垂深(m)", "南北坐标(m)", "东西坐标(m)",
                   "闭合方位(°)", "闭合位移(m)", "视平位移(m)", "狗腿度(°/30m)", "纵坐标(X)", "横坐标(Y)"]

        # 添加表头标签
        for col, header in enumerate(headers):
            label = QLabel(header)
            feature_layout.addWidget(label, 0, col + 1)  # 第一行是表头

        # 创建特征值输入行
        self.feature_inputs = []
        for row in range(2):
            # 添加特征标签
            feature_label = QLabel(f"特征{row + 1}")
            feature_layout.addWidget(feature_label, row + 1, 0)

            # 创建每列的输入/显示控件
            row_inputs = []
            for col in range(len(headers)):
                if col ==0:  # 井深列可编辑
                    input_widget = QLineEdit()
                    input_widget.textChanged.connect(lambda text, r=row: self.on_feature_depth_changed(text, r))
                else:  # 其他列只读
                    input_widget = QLineEdit()
                    input_widget.setReadOnly(True)
                    input_widget.setStyleSheet("background-color: rgb(240, 240, 240);")
                feature_layout.addWidget(input_widget, row + 1, col + 1)
                row_inputs.append(input_widget)
            self.feature_inputs.append(row_inputs)

        layout.addWidget(feature_group)

        # 创建主数据表格
        self.main_table = QTableWidget()
        self.setup_main_table()

        layout.addWidget(self.main_table)
        return view

    def create_angle_view(self):
        """创建夹角计算视图"""
        view = QWidget()
        layout = QHBoxLayout(view)
        layout.setSpacing(20)  # 设置左右两个面板的间距

        # 创建左右两个计算部分
        angle_panel = self.create_angle_calc_panel()
        depth_panel = self.create_depth_calc_panel()

        # 添加到主布局
        layout.addWidget(angle_panel, 1)  # 比例1
        layout.addWidget(depth_panel, 1)  # 比例1

        return view

    def create_angle_calc_panel(self):
        """创建夹角计算面板"""
        panel = QGroupBox("夹角公式计算")
        layout = QVBoxLayout(panel)
        layout.setSpacing(15)  # 设置垂直间距

        # 创建井型选择
        type_layout = QHBoxLayout()
        type_layout.addWidget(QLabel("井型选择:"))
        self.angle_well_type = QComboBox()
        self.angle_well_type.addItems(["上倾井", "下倾井"])
        self.angle_well_type.currentTextChanged.connect(self.on_angle_type_changed)
        type_layout.addWidget(self.angle_well_type)
        type_layout.addStretch()
        layout.addLayout(type_layout)

        # 创建输入参数区域
        input_group = QGroupBox("输入参数")
        input_layout = QGridLayout(input_group)
        input_layout.setSpacing(10)  # 设置网格间距

        # 创建输入字段
        input_fields = [
            ("当前井斜 (°):", "current_angle"),
            ("目标井斜 (°):", "target_angle"),
            ("垂深 (m):", "vertical_depth"),
            ("地层倾角 (°):", "formation_angle")
        ]

        self.angle_inputs = {}

        for i, (label, field_name) in enumerate(input_fields):
            # 添加标签
            label_widget = QLabel(label)
            label_widget.setMinimumWidth(120)  # 设置最小宽度
            input_layout.addWidget(label_widget, i, 0)

            # 创建输入框
            line_edit = QLineEdit()
            line_edit.setObjectName(field_name)
            line_edit.setMinimumWidth(100)  # 设置最小宽度
            line_edit.textChanged.connect(self.on_angle_input_changed)
            input_layout.addWidget(line_edit, i, 1)

            self.angle_inputs[field_name] = line_edit

        layout.addWidget(input_group)

        # 创建输出参数区域
        output_group = QGroupBox("计算结果")
        output_layout = QGridLayout(output_group)
        output_layout.setSpacing(10)  # 设置网格间距

        # 创建输出字段
        output_fields = [
            ("真厚度 (m):", "true_thickness")
        ]

        self.angle_outputs = {}

        for i, (label, field_name) in enumerate(output_fields):
            # 添加标签
            label_widget = QLabel(label)
            label_widget.setMinimumWidth(120)  # 设置最小宽度
            output_layout.addWidget(label_widget, i, 0)

            # 创建结果显示标签
            result_label = QLabel()
            result_label.setObjectName(field_name)
            result_label.setFrameStyle(QFrame.Panel | QFrame.Sunken)
            result_label.setMinimumWidth(150)  # 设置最小宽度
            result_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
            output_layout.addWidget(result_label, i, 1)

            self.angle_outputs[field_name] = result_label

        layout.addWidget(output_group)
        layout.addStretch()

        return panel

    def create_depth_calc_panel(self):
        """创建预测垂深计算面板"""
        panel = QGroupBox("预测垂深计算")
        layout = QVBoxLayout(panel)
        layout.setSpacing(15)  # 设置垂直间距

        # 创建井型选择
        type_layout = QHBoxLayout()
        type_layout.addWidget(QLabel("井型选择:"))
        self.depth_well_type = QComboBox()
        self.depth_well_type.addItems(["上倾井", "下倾井"])
        self.depth_well_type.currentTextChanged.connect(self.on_depth_type_changed)
        type_layout.addWidget(self.depth_well_type)
        type_layout.addStretch()
        layout.addLayout(type_layout)

        # 创建输入参数区域
        input_group = QGroupBox("输入参数")
        input_layout = QGridLayout(input_group)
        input_layout.setSpacing(10)  # 设置网格间距

        # 创建输入字段
        input_fields = [
            ("真厚度 (m):", "true_thickness"),
            ("地层倾角 (°):", "formation_angle"),
            ("本井特征点垂深 (m):", "current_depth"),
            ("平面距离 (m):", "plane_distance")
        ]

        self.depth_inputs = {}

        for i, (label, field_name) in enumerate(input_fields):
            # 添加标签
            label_widget = QLabel(label)
            label_widget.setMinimumWidth(120)  # 设置最小宽度
            input_layout.addWidget(label_widget, i, 0)

            # 创建输入框
            line_edit = QLineEdit()
            line_edit.setObjectName(field_name)
            line_edit.setMinimumWidth(100)  # 设置最小宽度
            line_edit.textChanged.connect(self.on_depth_input_changed)
            input_layout.addWidget(line_edit, i, 1)

            self.depth_inputs[field_name] = line_edit

        layout.addWidget(input_group)

        # 创建输出参数区域
        output_group = QGroupBox("计算结果")
        output_layout = QGridLayout(output_group)
        output_layout.setSpacing(10)  # 设置网格间距

        # 创建输出字段
        output_fields = [
            ("预测垂深:", "predicted_depth")

        ]

        self.depth_outputs = {}

        for i, (label, field_name) in enumerate(output_fields):
            # 添加标签
            label_widget = QLabel(label)
            label_widget.setMinimumWidth(120)  # 设置最小宽度
            output_layout.addWidget(label_widget, i, 0)

            # 创建结果显示标签
            result_label = QLabel()
            result_label.setObjectName(field_name)
            result_label.setFrameStyle(QFrame.Panel | QFrame.Sunken)
            result_label.setMinimumWidth(150)  # 设置最小宽度
            result_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
            output_layout.addWidget(result_label, i, 1)

            self.depth_outputs[field_name] = result_label

        layout.addWidget(output_group)
        layout.addStretch()

        return panel

    def on_angle_type_changed(self, well_type):
        """处理夹角计算井型变化"""
        self.on_angle_input_changed()  # 重新计算结果

    def on_depth_type_changed(self, well_type):
        """处理预测垂深井型变化"""
        self.on_depth_input_changed()  # 重新计算结果

    def on_angle_input_changed(self):
        """处理夹角计算输入变化"""
        # 获取输入值
        current_angle = float(self.angle_inputs["current_angle"].text() or "0")
        target_angle = float(self.angle_inputs["target_angle"].text() or "0")
        vertical_depth = float(self.angle_inputs["vertical_depth"].text() or "0")
        formation_angle = float(self.angle_inputs["formation_angle"].text() or "0")

        # 判断井型
        is_upward = self.angle_well_type.currentText() == "上倾井"

        vertical_depth = vertical_depth if is_upward else -vertical_depth

        # 计算真厚度
        true_thickness = vertical_depth * math.sin(math.radians(formation_angle))

        # 更新输出结果
        self.angle_outputs["true_thickness"].setText(f"{true_thickness:.4f}")

    def on_depth_input_changed(self):
        """处理预测垂深计算输入变化"""

        # 获取输入值
        true_thickness = float(self.depth_inputs["true_thickness"].text() or "0")
        formation_angle = float(self.depth_inputs["formation_angle"].text() or "0")
        current_depth = float(self.depth_inputs["current_depth"].text() or "0")
        plane_distance = float(self.depth_inputs["plane_distance"].text() or "0")

        # 判断井型
        is_upward = self.depth_well_type.currentText() == "上倾井"

        # 计算预测垂深
        if is_upward:
            predicted_depth = current_depth + (true_thickness / math.cos(math.radians(formation_angle))) - \
                              (plane_distance * math.tan(math.radians(formation_angle)))
        else:
            predicted_depth = current_depth + (true_thickness / math.cos(math.radians(formation_angle))) + \
                              (plane_distance * math.tan(math.radians(formation_angle)))

        # 更新输出结果
        self.depth_outputs["predicted_depth"].setText(f"{predicted_depth:.4f}")

    def create_thickness_view(self):
        """创建真厚度计算视图"""
        view = QWidget()
        layout = QVBoxLayout(view)
        layout.setSpacing(15)  # 设置垂直间距

        # 创建计算结果表格
        self.thickness_table = QTableWidget()
        self.setup_thickness_table()
        layout.addWidget(self.thickness_table)

        return view

    def setup_thickness_table(self):
        """设置真厚度计算表格"""
        headers = ["深度(m)", "地层真倾向(°)", "地层真倾角(°)", "井轨迹方位(°)", "沿井轨迹视倾角(°)"]
        self.setup_table(self.thickness_table, headers, 4)  # 前4列可编辑

        # 添加初始数据
        initial_data = [
            [0.00, 45.00, 30.00, 45.00, 30.0000],  # 井轨迹与地层倾向一致
            [100.00, 45.00, 30.00, 135.00, 21.2132],  # 井轨迹与地层倾向垂直
            [200.00, 45.00, 30.00, 225.00, 30.0000],  # 井轨迹与地层倾向相反
            [300.00, 45.00, 30.00, 90.00, 21.2132],  # 井轨迹与地层倾向成90度
            [400.00, 45.00, 30.00, 0.00, 21.2132]  # 井轨迹与地层倾向成0度
        ]

        # 填充初始数据
        for row_data in initial_data:
            row = self.thickness_table.rowCount()
            self.thickness_table.insertRow(row)
            for col, value in enumerate(row_data):
                item = QTableWidgetItem(str(value))
                if col == self.thickness_table.columnCount() - 1:  # 最后一列
                    item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                    item.setBackground(QColor(240, 240, 240))
                self.thickness_table.setItem(row, col, item)

        # 连接单元格变化信号
        self.thickness_table.itemChanged.connect(self.on_thickness_table_changed)

    def on_thickness_table_changed(self, item):
        """处理真厚度表格数据变更"""
        if not hasattr(self, 'is_calculating') or not self.is_calculating:
            try:
                self.is_calculating = True
                row = item.row()
                col = item.column()

                # 如果修改的是前4列，更新视倾角
                if col in [1, 2, 3]:  # 地层真倾向、地层真倾角、井轨迹方位
                    self.update_visual_dip(row)

            finally:
                self.is_calculating = False

    def calculate_visual_dip(self, true_dip_direction, true_dip_angle, well_azimuth):
        """计算沿井轨迹视倾角
        Args:
            true_dip_direction: 地层真倾向(°)
            true_dip_angle: 地层真倾角(°)
            well_azimuth: 井轨迹方位(°)
        Returns:
            float: 沿井轨迹视倾角(°)
        """
        try:
            # 计算方位角差
            azimuth_diff = abs(well_azimuth - true_dip_direction)
            if azimuth_diff > 180:
                azimuth_diff = 360 - azimuth_diff

            # 计算视倾角
            visual_dip = math.degrees(math.asin(math.sin(math.radians(true_dip_angle)) *
                                                math.cos(math.radians(azimuth_diff))))
            return round(visual_dip, 9)  # 保留4位小数
        except Exception as e:
            print(f"计算视倾角错误: {str(e)}")
            return 0.0

    def update_visual_dip(self, row):
        """更新指定行的视倾角
        Args:
            row: 要更新的行号
        """
        try:
            # 获取前4列的值，添加空值检查
            true_dip_direction_item = self.thickness_table.item(row, 1)
            true_dip_angle_item = self.thickness_table.item(row, 2)
            well_azimuth_item = self.thickness_table.item(row, 3)

            # 检查是否有空值
            if not all([true_dip_direction_item, true_dip_angle_item, well_azimuth_item]):
                return

            # 获取值并转换为float
            try:
                true_dip_direction = float(true_dip_direction_item.text() or 0)
                true_dip_angle = float(true_dip_angle_item.text() or 0)
                well_azimuth = float(well_azimuth_item.text() or 0)
            except ValueError:
                return

            # 计算视倾角
            visual_dip = self.calculate_visual_dip(true_dip_direction, true_dip_angle, well_azimuth)

            # 更新最后一列
            item = QTableWidgetItem()
            item.setFlags(item.flags() & ~Qt.ItemIsEditable)
            item.setBackground(QColor(240, 240, 240))

            # 使用DISPLAY_FORMATS中的格式显示
            display_format = DISPLAY_FORMATS['thickness_table'].get(4, '.4f')
            item.setText(format(Decimal(str(visual_dip)), display_format))

            self.thickness_table.setItem(row, 4, item)
        except Exception as e:
            print(f"更新视倾角错误: {str(e)}")

    def setup_main_table(self):
        """设置主数据表格"""
        headers = ["井深(m)", "井斜(°)", "方位(°)", "垂深(m)", "南北坐标(m)", "东西坐标(m)",
                   "闭合方位(°)", "闭合位移(m)", "视平位移(m)", "狗腿度(°/30m)", "纵坐标(X)", "横坐标(Y)"]

        initial_data = [
            [0.00, 0.00, 160.26, 0.00, 0, 0, 0, 0, 0, 0, 3246136.98, 18550536.42],
            [32.87, 0.27, 160.26, 32.87, - 0.07, 0.03, 160.26, 0.08, 0.07, 0.25, 3246136.91, 18550536.45],
            [32.87, 0.27, 160.26, 32.87, - 0.07, 0.03, 160.26, 0.08, 0.07, 0.25, 3246136.91, 18550536.45],
            [60.08, 0.45, 205.66, 60.08, - 0.23, 0.00, 179.62, 0.23, 0.23, 0.36, 3246136.75, 18550536.42],
            [87.61, 0.53, 281.06, 87.61, - 0.30, 0.00, 179.71, 0.30, 0.30, 0.66, 3246136.68, 18550536.42],
            [32.87, 0.27, 160.26, 32.87, - 0.07, 0.03, 160.26, 0.08, 0.07, 0.25, 3246136.91, 18550536.45],
            [60.08, 0.45, 205.66, 60.08, - 0.23, 0.00, 179.62, 0.23, 0.23, 0.36, 3246136.75, 18550536.42],
            [32.87, 0.27, 160.26, 32.87, - 0.07, 0.03, 160.26, 0.08, 0.07, 0.25, 3246136.91, 18550536.45],
            [60.08, 0.45, 205.66, 60.08, - 0.23, 0.00, 179.62, 0.23, 0.23, 0.36, 3246136.75, 18550536.42],
            [87.61, 0.53, 281.06, 87.61, - 0.30, 0.00, 179.71, 0.30, 0.30, 0.66, 3246136.68, 18550536.42]
        ]

        self.setup_table(self.main_table, headers, 3, initial_data)
        self.main_table.itemChanged.connect(self.on_main_table_changed)

    def setup_table(self, table, headers, editable_columns, initial_data=None):
        """通用的表格设置方法
        Args:
            table: 要设置的表格对象
            headers: 表头列表
            editable_columns: 可编辑的列数
            initial_data: 初始数据（可选）
        """
        # 设置基本属性
        table.setColumnCount(len(headers))
        table.setHorizontalHeaderLabels(headers)
        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        table.setSelectionMode(QTableWidget.ContiguousSelection)
        table.setEditTriggers(QTableWidget.DoubleClicked | QTableWidget.EditKeyPressed)

        # 设置初始数据
        if initial_data:
            table.setRowCount(len(initial_data))
            for row, row_data in enumerate(initial_data):
                for col, value in enumerate(row_data):
                    item = QTableWidgetItem(str(value))
                    if col >= editable_columns:
                        item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                        item.setBackground(QColor(240, 240, 240))
                    table.setItem(row, col, item)

        # 设置不可编辑列的默认样式
        for col in range(editable_columns, table.columnCount()):
            for row in range(table.rowCount()):
                item = table.item(row, col)
                if item is None:
                    item = QTableWidgetItem()
                    table.setItem(row, col, item)
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                item.setBackground(QColor(240, 240, 240))

        # 设置右键菜单
        table.setContextMenuPolicy(Qt.CustomContextMenu)
        table.customContextMenuRequested.connect(
            lambda pos: self.show_table_context_menu(table, pos)
        )

        # 设置列标题栏右键菜单
        header = table.horizontalHeader()
        header.setContextMenuPolicy(Qt.CustomContextMenu)
        header.customContextMenuRequested.connect(
            lambda pos: self.show_table_header_context_menu(table, pos, editable_columns)
        )

        # 安装事件过滤器
        table.installEventFilter(self)

    def show_table_context_menu(self, table, pos):
        """通用的表格右键菜单"""
        menu = QMenu(self)

        # 添加通用菜单项
        copy_action = menu.addAction("复制")
        paste_action = menu.addAction("粘贴")
        menu.addSeparator()
        add_row_action = menu.addAction("添加行")
        delete_row_action = menu.addAction("删除行")

        # 连接动作
        copy_action.triggered.connect(lambda: self.copy_table_cells(table))
        paste_action.triggered.connect(lambda: self.paste_table_cells(table))
        add_row_action.triggered.connect(lambda: self.add_table_row(table))
        delete_row_action.triggered.connect(lambda: self.delete_table_rows(table))

        menu.exec(table.viewport().mapToGlobal(pos))

    def copy_table_cells(self, table):
        """通用的复制表格单元格"""
        selected = table.selectedRanges()
        if not selected:
            return

        text = []
        for r in range(selected[0].topRow(), selected[0].bottomRow() + 1):
            row = []
            for c in range(selected[0].leftColumn(), selected[0].rightColumn() + 1):
                item = table.item(r, c)
                row.append(item.text() if item else "")
            text.append("\t".join(row))

        QApplication.clipboard().setText("\n".join(text))

    def paste_table_cells(self, table):
        """通用的粘贴表格单元格"""
        clipboard = QApplication.clipboard()
        text = clipboard.text()
        if not text:
            return

        current_row = table.currentRow()
        current_col = table.currentColumn()

        if current_row < 0:
            current_row = 0
        if current_col < 0:
            current_col = 0

        rows = text.split("\n")
        for i, row_text in enumerate(rows):
            if not row_text:
                continue

            columns = row_text.split("\t")
            for j, value in enumerate(columns):
                target_row = current_row + i
                target_col = current_col + j

                # 确保有足够的行
                while target_row >= table.rowCount():
                    self.add_table_row(table)

                # 确保有足够的列
                while target_col >= table.columnCount():
                    table.insertColumn(target_col)

                # 创建item并设置值
                item = QTableWidgetItem(value.strip())

                # 根据表格类型设置编辑权限
                if table == self.thickness_table:
                    # 真厚度表格：最后一列不可编辑
                    if target_col == table.columnCount() - 1:
                        item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                        item.setBackground(QColor(240, 240, 240))
                else:
                    # 其他表格：前3列可编辑
                    if target_col >= 3:
                        item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                        item.setBackground(QColor(240, 240, 240))

                table.setItem(target_row, target_col, item)

                # 如果是真厚度表格，更新视倾角计算
                if table == self.thickness_table and target_col in [1, 2, 3]:
                    self.update_visual_dip(target_row)

    def add_table_row(self, table):
        """通用的添加表格行"""
        current_row = table.currentRow()
        if current_row < 0:
            current_row = table.rowCount()

        table.insertRow(current_row)

        # 设置不可编辑列的默认样式
        for col in range(table.columnCount()):
            item = QTableWidgetItem()
            if table == self.thickness_table:
                # 真厚度表格：最后一列不可编辑
                if col == table.columnCount() - 1:
                    item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                    item.setBackground(QColor(240, 240, 240))
                # 设置默认值
                if col == 1:  # 地层真倾向
                    item.setText("45.00")
                elif col == 2:  # 地层真倾角
                    item.setText("30.00")
                elif col == 3:  # 井轨迹方位
                    item.setText("45.00")
            else:
                # 其他表格：前3列可编辑
                if col >= 3:
                    item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                    item.setBackground(QColor(240, 240, 240))
            table.setItem(current_row, col, item)

        # 如果是真厚度表格，计算新行的视倾角
        if table == self.thickness_table:
            self.update_visual_dip(current_row)

    def delete_table_rows(self, table):
        """通用的删除表格行"""
        rows = set(item.row() for item in table.selectedItems())
        for row in sorted(rows, reverse=True):
            table.removeRow(row)

    def on_main_table_changed(self, item):
        """处理主表格数据变更"""
        if not hasattr(self, 'is_calculating') or not self.is_calculating:
            try:
                self.is_calculating = True
                row = item.row()
                col = item.column()

                # 只处理井深、井斜、方位列的变更
                if col <= 2:
                    self.calculate_row_values(row)

                # 更新特征值计算
                self.update_feature_calculations()

            finally:
                self.is_calculating = False

    def calculate_row_values(self, row):
        """计算单行数据"""
        try:
            # 获取基本数据
            well_depth = self.get_cell_value(self.main_table, row, 0)
            inclination = self.get_cell_value(self.main_table, row, 1)
            azimuth = self.get_cell_value(self.main_table, row, 2)

            if well_depth is None or inclination is None or azimuth is None:
                return

            # 创建计算器实例
            calculator = OtherParameters()

            # 第一行特殊处理
            if row == 0:
                # vertical_depth = (well_depth * Decimal(math.cos(math.radians(float(inclination))))).quantize(
                #     CALCULATION_PRECISION)
                vertical_depth = Decimal('0.0')
                ns_coordinates = Decimal('0')
                ew_coordinates = Decimal('0')
                closed_orientation = azimuth
                closed_displacement = Decimal('0')
                eye_displacement = Decimal('0')
                dogleg_degree = Decimal('0')
                ordinate = Decimal('3246136.98')
                abscissa = Decimal('18550536.42')
            else:
                # 获取上一行数据
                prev_depth = self.get_cell_value(self.main_table, row - 1, 0)
                prev_inclination = self.get_cell_value(self.main_table, row - 1, 1)
                prev_azimuth = self.get_cell_value(self.main_table, row - 1, 2)
                prev_vertical_depth = self.get_cell_value(self.main_table, row - 1, 3)
                prev_ns = self.get_cell_value(self.main_table, row - 1, 4)
                prev_ew = self.get_cell_value(self.main_table, row - 1, 5)
                prev_closed_orientation=self.get_cell_value(self.main_table, row - 1, 6)
                prev_closed_displacement = self.get_cell_value(self.main_table, row - 1, 7)
                prev_eye_displacement = self.get_cell_value(self.main_table, row - 1, 8)
                prev_dogleg_degree = self.get_cell_value(self.main_table, row - 1, 9)
                prev_ordinate = self.get_cell_value(self.main_table, row - 1, 10)
                prev_abscissa = self.get_cell_value(self.main_table, row - 1, 11)


                if prev_depth is None or prev_inclination is None or prev_azimuth is None:
                    return

                prev_data = WellTrajectoryData(
                    well_depth=prev_depth,
                    well_slope=prev_inclination,
                    azimuth=prev_azimuth,
                    vertical_depth=prev_vertical_depth,
                    ns_coordinates=prev_ns,
                    ew_coordinates=prev_ew,
                    closed_orientation=prev_closed_orientation,
                    closed_displacement=prev_closed_displacement,
                    eye_displacement=prev_eye_displacement,
                    dogleg_degree=prev_dogleg_degree,
                    ordinate=prev_ordinate,
                    abscissa=prev_abscissa
                )

                # if prev_data ==None or cur_data==None:
                #     return
                # # 计算段长
                # segment = (well_depth - prev_depth).quantize(CALCULATION_PRECISION)
                # if segment <= 0:
                #     return

                # # 计算最小曲率系数
                # epsilon = (Decimal(math.cos(math.radians(float(inclination - prev_inclination)))) - \
                #            Decimal(math.sin(math.radians(float(prev_inclination)))) * \
                #            Decimal(math.sin(math.radians(float(inclination)))) * \
                #            (Decimal('1') - Decimal(math.cos(math.radians(float(azimuth - prev_azimuth)))))).quantize(
                #     CALCULATION_PRECISION)


                # # 处理epsilon接近1的情况
                # if abs(epsilon - Decimal('1')) < Decimal('1e-10'):
                #     min_curvature = Decimal('1')
                # else:
                #     min_curvature = Decimal(
                #         str(calculator.calculate_min_curvature(math.acos(float(epsilon))))).quantize(
                #         CALCULATION_PRECISION)
                #
                # # 计算垂深
                # vertical_depth = (prev_vertical_depth + segment / Decimal('2') * \
                #                   (Decimal(math.cos(math.radians(float(prev_inclination)))) + \
                #                    Decimal(math.cos(math.radians(float(inclination))))) * min_curvature).quantize(
                #     CALCULATION_PRECISION
                #
                #
                # # 计算坐标变化
                # ns_change = (segment / Decimal('2') * (Decimal(math.sin(math.radians(float(prev_inclination)))) * \
                #                                        Decimal(math.cos(math.radians(float(prev_azimuth)))) + \
                #                                        Decimal(math.sin(math.radians(float(inclination)))) * \
                #                                        Decimal(math.cos(
                #                                            math.radians(float(azimuth))))) * min_curvature).quantize(
                #     CALCULATION_PRECISION)
                # ew_change = (segment / Decimal('2') * (Decimal(math.sin(math.radians(float(prev_inclination)))) * \
                #                                        Decimal(math.sin(math.radians(float(prev_azimuth)))) + \
                #                                        Decimal(math.sin(math.radians(float(inclination)))) * \
                #                                        Decimal(math.sin(
                #                                            math.radians(float(azimuth))))) * min_curvature).quantize(
                #     CALCULATION_PRECISION)
                #
                # # 更新坐标
                # ns_coordinates = (prev_ns + ns_change).quantize(CALCULATION_PRECISION)
                # ew_coordinates = (prev_ew + ew_change).quantize(CALCULATION_PRECISION)
                #
                # # 计算闭合方位
                # closed_orientation = Decimal(str(calculator.calculate_closed_direction(
                #     calculator.calculate_theta(float(ns_coordinates), float(ew_coordinates))))).quantize(
                #     CALCULATION_PRECISION)
                #
                # # 计算位移
                # closed_displacement = Decimal(math.sqrt(float(ns_coordinates ** 2 + ew_coordinates ** 2))).quantize(
                #     CALCULATION_PRECISION)
                #
                # # 计算视平位移
                # design_azimuth = Decimal(self.design_azimuth.text() or "188.00")
                # eye_displacement = (closed_displacement * Decimal(
                #     math.cos(math.radians(float(design_azimuth - closed_orientation))))).quantize(CALCULATION_PRECISION)
                #
                # # 计算狗腿度
                # if segment > 0:
                #     dogleg_degree = Decimal(math.degrees(math.acos(float(epsilon))) * 30 / float(segment)).quantize(
                #         CALCULATION_PRECISION)
                # else:
                #     dogleg_degree = Decimal('0')
                #
                # # 计算坐标
                # ordinate = (prev_ordinate - ns_change).quantize(CALCULATION_PRECISION)
                # abscissa = (prev_abscissa + ew_change).quantize(CALCULATION_PRECISION)
                cur_data=WellTrajectoryData(
                        well_depth=well_depth,
                        well_slope=inclination,
                        azimuth=azimuth,
                        # vertical_depth=Decimal('0.0'),
                        # ns_coordinates=Decimal('0'),
                        # ew_coordinates=Decimal('0'),
                        # closed_orientation=Decimal('0'),
                        # closed_displacement=Decimal('0'),
                        # eye_displacement=Decimal('0'),
                        # dogleg_degree=Decimal('0'),
                        # ordinate=Decimal('3246136.98'),
                        # abscissa=Decimal('18550536.42')
                )

                res= calculator.calculate_other_parameters((prev_data, cur_data))
                print(res)
                if res is not None:
                    vertical_depth,  ns_coordinates, ew_coordinates, closed_orientation, closed_displacement, eye_displacement, dogleg_degree, ordinate, abscissa=res
                # 设置计算结果
                    print(vertical_depth,  ns_coordinates, ew_coordinates, closed_orientation, closed_displacement, eye_displacement, dogleg_degree, ordinate, abscissa)
                    self.set_cell_value(self.main_table, row, 3, vertical_depth)
                    self.set_cell_value(self.main_table, row, 4, ns_coordinates)
                    self.set_cell_value(self.main_table, row, 5, ew_coordinates)
                    self.set_cell_value(self.main_table, row, 6, closed_orientation)
                    self.set_cell_value(self.main_table, row, 7, closed_displacement)
                    self.set_cell_value(self.main_table, row, 8, eye_displacement)
                    self.set_cell_value(self.main_table, row, 9, dogleg_degree)
                    self.set_cell_value(self.main_table, row, 10, ordinate)
                    self.set_cell_value(self.main_table, row, 11, abscissa)

        except Exception as e:
            self.statusBar().showMessage(f"计算错误: {str(e)}")
            print(f"计算错误: {str(e)}")

    def get_cell_value(self, table, row, col):
        """获取单元格数值"""
        item = table.item(row, col)
        if item and item.text():
            try:
                # 使用Decimal来保持高精度
                return Decimal(item.text())
            except ValueError:
                return None
        return None

    def set_cell_value(self, table, row, col, value):
        """设置单元格数值，根据不同列使用不同的显示精度"""
        if value is None:
            value = ""
        else:
            try:
                # 确定使用哪个表格的格式
                if table == self.main_table:
                    formats = DISPLAY_FORMATS['main_table']
                elif table == self.thickness_table:
                    formats = DISPLAY_FORMATS['thickness_table']
                else:
                    formats = {col: '.2f'}  # 默认格式

                # 获取该列的显示格式
                display_format = formats.get(col, '.2f')

                # 转换为Decimal并格式化显示
                if isinstance(value, (int, float, Decimal)):
                    decimal_value = Decimal(str(value))
                    value = format(decimal_value, display_format)
                else:
                    value = str(value)

            except (ValueError, TypeError) as e:
                print(f"格式化错误: {str(e)}")
                value = str(value)

        item = QTableWidgetItem(value)

        # 设置单元格编辑权限
        if table == self.main_table:
            if col >= 3:  # 主表格：前3列可编辑
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                item.setBackground(QColor(240, 240, 240))
        elif table == self.thickness_table:
            if col == table.columnCount() - 1:  # 真厚度表格：最后一列不可编辑
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                item.setBackground(QColor(240, 240, 240))

        table.setItem(row, col, item)

    def on_feature_changed(self, item):
        """处理特征值变更"""
        if not hasattr(self, 'is_calculating') or not self.is_calculating:
            try:
                self.is_calculating = True
                self.update_feature_calculations()
            finally:
                self.is_calculating = False

    def update_feature_calculations(self):
        """更新特征值计算"""
        try:
            # 获取最后两行数据
            last_row = self.main_table.rowCount() - 1
            if last_row < 1:
                return

            # 创建计算器实例
            true_thickness = TrueThickness()
            true_inclination = TrueInclination()
            true_inclination_to_view_inclination = TrueInclinationToViewInclination()


            # 获取特征值
            for feature_row in range(2):
                feature_value = self.feature_inputs[feature_row][0].text()  # 获取特征值
                if feature_value is None:
                    continue
                try:
                    feature_value = float(feature_value)
                except ValueError:
                    continue

                # 获取数据
                data1 = self.create_trajectory_data(last_row - 1)
                data2 = self.create_trajectory_data(last_row)

                # 计算真实倾角和厚度
                is_inclined = feature_row == 0  # 特征1为上倾，特征2为下倾

                true_incl = true_inclination.calculate_true_inclination(
                    data2.vertical_depth,
                    data2.eye_displacement,
                    feature_value,
                    is_inclined
                )

                true_thick = true_thickness.calculate_true_thickness(
                    data1,
                    data2,
                    feature_value,
                    is_inclined
                )

                # 设置结果
                self.feature_inputs[feature_row][1].setText(f"{true_incl:.2f}")
                self.feature_inputs[feature_row][2].setText(f"{true_thick:.2f}")



        except Exception as e:
            self.statusBar().showMessage(f"特征值计算错误: {str(e)}")
            print(f"特征值计算错误: {str(e)}")

    def create_trajectory_data(self, row):
        """创建轨迹数据对象"""
        data = WellTrajectoryData()
        if row >= 0 and row < self.main_table.rowCount():
            data.well_depth = self.get_cell_value(self.main_table, row, 0) or 0
            data.well_slope = self.get_cell_value(self.main_table, row, 1) or 0
            data.azimuth = self.get_cell_value(self.main_table, row, 2) or 0
            data.vertical_depth = self.get_cell_value(self.main_table, row, 3) or 0
            data.ns_coordinates = self.get_cell_value(self.main_table, row, 4) or 0
            data.ew_coordinates = self.get_cell_value(self.main_table, row, 5) or 0
            data.closed_orientation = self.get_cell_value(self.main_table, row, 6) or 0
            data.closed_displacement = self.get_cell_value(self.main_table, row, 7) or 0
            data.eye_displacement = self.get_cell_value(self.main_table, row, 8) or 0
            data.dogleg_degree = self.get_cell_value(self.main_table, row, 9) or 0
            data.ordinate = self.get_cell_value(self.main_table, row, 10) or 0
            data.abscissa = self.get_cell_value(self.main_table, row, 11) or 0
        return data

    def import_data(self):
        """导入数据"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择Excel文件", "", "Excel Files (*.xlsx *.xls)")
        if file_path:
            try:
                df = pd.read_excel(file_path)
                self.main_table.setRowCount(len(df))
                for row in range(len(df)):
                    for col in range(min(len(df.columns), self.main_table.columnCount())):
                        value = df.iat[row, col] if not pd.isna(df.iat[row, col]) else ""
                        self.set_cell_value(self.main_table, row, col, value)
                self.statusBar().showMessage(f"成功导入 {len(df)} 行数据")
            except Exception as e:
                QMessageBox.critical(self, "导入错误", f"导入Excel文件时出错：{str(e)}")

    def clear_data(self):
        """清空数据"""
        self.main_table.setRowCount(0)
        self.thickness_table.setRowCount(0)
        self.well_number.clear()
        self.unit_name.clear()

        # 清空特征值面板
        if hasattr(self, 'feature_inputs'):
            for row in self.feature_inputs:
                for widget in row:
                    widget.clear()

        self.statusBar().showMessage("数据已清空")

    def export_data(self):
        """导出数据"""
        file_path, _ = QFileDialog.getSaveFileName(
            self, "保存Excel文件", "", "Excel Files (*.xlsx)")
        if file_path:
            try:
                # 创建数据框
                data = []
                headers = []
                for col in range(self.main_table.columnCount()):
                    headers.append(self.main_table.horizontalHeaderItem(col).text())

                for row in range(self.main_table.rowCount()):
                    row_data = []
                    for col in range(self.main_table.columnCount()):
                        value = self.get_cell_value(self.main_table, row, col)
                        row_data.append(value if value is not None else "")
                    data.append(row_data)

                # 创建DataFrame并保存
                df = pd.DataFrame(data, columns=headers)
                df.to_excel(file_path, index=False)
                self.statusBar().showMessage(f"数据已导出到 {file_path}")
            except Exception as e:
                QMessageBox.critical(self, "导出错误", f"导出Excel文件时出错：{str(e)}")

    def update_calculations(self):
        """更新计算结果"""
        # 更新主表格计算
        for row in range(self.main_table.rowCount()):
            self.calculate_row_values(row)

        # 更新特征值计算
        self.update_feature_calculations()

    def on_feature_depth_changed(self, text, feature_row):
        """处理特征值井深变化"""
        try:
            if not text:
                # 清空该行的所有计算结果
                for col in range(1, len(self.feature_inputs[feature_row])):
                    self.feature_inputs[feature_row][col].setText("")
                return

            target_depth = float(text)

            # # 在主表格中找到相邻的两个数据点
            # depths = []
            # for row in range(self.main_table.rowCount()):
            #     depth_item = self.main_table.item(row, 0)
            #     if depth_item and depth_item.text():
            #         depth = float(depth_item.text())
            #         depths.append((depth, row))
            #
            # if not depths:
            #     return

            # 排序并找到相邻点
            # depths.sort()
            # lower_row = upper_row = None

            # for i, (depth, row) in enumerate(depths):
            #     if depth > target_depth:
            #         if i > 0:
            #             lower_row = depths[i - 1][1]
            #             upper_row = row
            #         break
            lower_data, upper_data=ExcelFinder(self.main_table).find_data(target_depth)

            if lower_data is not None and upper_data is not None:
                # # 获取上下两点的数据
                # lower_data = WellTrajectoryData()
                # upper_data = WellTrajectoryData()
                #
                # # 填充下点数据
                # lower_data.well_depth = float(self.main_table.item(lower_row, 0).text() or 0)
                # lower_data.well_slope = float(self.main_table.item(lower_row, 1).text() or 0)
                # lower_data.azimuth = float(self.main_table.item(lower_row, 2).text() or 0)
                # lower_data.vertical_depth = float(self.main_table.item(lower_row, 3).text() or 0)
                # lower_data.ns_coordinates = float(self.main_table.item(lower_row, 4).text() or 0)
                # lower_data.ew_coordinates = float(self.main_table.item(lower_row, 5).text() or 0)
                # lower_data.closed_orientation = float(self.main_table.item(lower_row, 6).text() or 0)
                # lower_data.closed_displacement = float(self.main_table.item(lower_row, 7).text() or 0)
                # lower_data.eye_displacement = float(self.main_table.item(lower_row, 8).text() or 0)
                # lower_data.dogleg_degree = float(self.main_table.item(lower_row, 9).text() or 0)
                # lower_data.ordinate = float(self.main_table.item(lower_row, 10).text() or 0)
                # lower_data.abscissa = float(self.main_table.item(lower_row, 11).text() or 0)
                #
                # # 填充上点数据
                # upper_data.well_depth = float(self.main_table.item(upper_row, 0).text() or 0)
                # upper_data.well_slope = float(self.main_table.item(upper_row, 1).text() or 0)
                # upper_data.azimuth = float(self.main_table.item(upper_row, 2).text() or 0)
                # upper_data.vertical_depth = float(self.main_table.item(upper_row, 3).text() or 0)
                # upper_data.ns_coordinates = float(self.main_table.item(upper_row, 4).text() or 0)
                # upper_data.ew_coordinates = float(self.main_table.item(upper_row, 5).text() or 0)
                # upper_data.closed_orientation = float(self.main_table.item(upper_row, 6).text() or 0)
                # upper_data.closed_displacement = float(self.main_table.item(upper_row, 7).text() or 0)
                # upper_data.eye_displacement = float(self.main_table.item(upper_row, 8).text() or 0)
                # upper_data.dogleg_degree = float(self.main_table.item(upper_row, 9).text() or 0)
                # upper_data.ordinate = float(self.main_table.item(upper_row, 10).text() or 0)
                # upper_data.abscissa = float(self.main_table.item(upper_row, 11).text() or 0)

                # 创建插值计算器并计算
                calculator = EstimateEigenvalues((lower_data, upper_data))
                result = calculator.estimate_eigenvalues(target_depth)

                # 更新特征值显示
                self.feature_inputs[feature_row][1].setText(f"{result.well_slope:.2f}")
                self.feature_inputs[feature_row][2].setText(f"{result.azimuth:.2f}")
                self.feature_inputs[feature_row][3].setText(f"{result.vertical_depth:.2f}")
                self.feature_inputs[feature_row][4].setText(f"{result.ns_coordinates:.2f}")
                self.feature_inputs[feature_row][5].setText(f"{result.ew_coordinates:.2f}")
                self.feature_inputs[feature_row][6].setText(f"{result.closed_orientation:.2f}")
                self.feature_inputs[feature_row][7].setText(f"{result.closed_displacement:.2f}")
                self.feature_inputs[feature_row][8].setText(f"{result.eye_displacement:.2f}")
                self.feature_inputs[feature_row][9].setText(f"{result.dogleg_degree:.2f}")
                self.feature_inputs[feature_row][10].setText(f"{result.ordinate:.2f}")
                self.feature_inputs[feature_row][11].setText(f"{result.abscissa:.2f}")

        except ValueError as e:
            print(f"值错误: {str(e)}")
            # 清空该行的所有计算结果
            for col in range(1, len(self.feature_inputs[feature_row])):
                self.feature_inputs[feature_row][col].setText("")
        except Exception as e:
            print(f"其他错误: {str(e)}")
            print(f"插值计算错误: {str(e)}")
            # 清空该行的所有计算结果
            for col in range(1, len(self.feature_inputs[feature_row])):
                self.feature_inputs[feature_row][col].setText("")

    def show_table_header_context_menu(self, table, pos, editable_columns):
        """通用的表格列标题栏右键菜单
        Args:
            table: 当前操作的表格对象
            pos: 鼠标点击位置
            editable_columns: 可编辑的列数（从0开始）
        """
        menu = QMenu(self)

        # 获取点击的列
        column = table.horizontalHeader().logicalIndexAt(pos)
        if column < 0:
            return

        # 只对可编辑列显示批量编辑选项
        if column < editable_columns:
            edit_action = menu.addAction("批量编辑本列")
            edit_action.triggered.connect(lambda: self.batch_edit_table_column(table, column))

        menu.exec(table.horizontalHeader().mapToGlobal(pos))

    def batch_edit_table_column(self, table, column):
        """通用的批量编辑表格列方法
        Args:
            table: 当前操作的表格对象
            column: 要编辑的列索引
        """
        # 创建输入对话框
        value, ok = QInputDialog.getText(
            self,
            "批量编辑",
            f"请输入{table.horizontalHeaderItem(column).text()}的新值:",
            QLineEdit.Normal
        )

        if ok and value:
            try:
                # 验证输入值
                float_value = float(value)

                # 更新所有行的该列值
                for row in range(table.rowCount()):
                    item = QTableWidgetItem(str(float_value))
                    table.setItem(row, column, item)

                    # 根据不同表格类型处理后续计算
                    if table == self.main_table:
                        # 主表格：如果是前3列，触发计算
                        if column < 3:
                            self.calculate_row_values(row)
                    elif table == self.thickness_table:
                        # 真厚度表格：如果修改了参数列，重新计算视倾角
                        if column in [1, 2, 3]:
                            self.update_visual_dip(row)

            except ValueError:
                QMessageBox.warning(self, "输入错误", "请输入有效的数值")

    def eventFilter(self, obj, event):
        """事件过滤器，处理按键事件"""
        if isinstance(obj, QTableWidget) and event.type() == QEvent.KeyPress:
            # 处理回车键
            if event.key() == Qt.Key_Return and not obj.state() == QTableWidget.EditingState:
                current_row = obj.currentRow()
                current_col = obj.currentColumn()
                obj.insertRow(current_row + 1)
                obj.setCurrentCell(current_row + 1, current_col)
                return True

            # 处理复制操作 (Ctrl+C)
            elif event.key() == Qt.Key_C and event.modifiers() == Qt.ControlModifier:
                self.copy_table_cells(obj)
                return True

            # 处理粘贴操作 (Ctrl+V)
            elif event.key() == Qt.Key_V and event.modifiers() == Qt.ControlModifier:
                self.paste_table_cells(obj)
                return True

            # 处理删除键
            elif event.key() in (Qt.Key_Delete, Qt.Key_Backspace):
                for item in obj.selectedItems():
                    item.setText("")
                return True

        return super().eventFilter(obj, event)

    def switch_view(self, index):
        """切换视图"""
        self.stack_widget.setCurrentIndex(index)
        view_names = ["井眼轨迹", "夹角计算", "真厚度计算"]
        self.statusBar().showMessage(f"切换到{view_names[index]}视图")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = WellTrajectorySystem()
    window.show()
    sys.exit(app.exec())
